import { program } from 'commander';
import colors from 'colors/safe';

import * as Enums from '../utils/Enums';
import Printer from '../utils/Printer';
import ExecuteHelper from '../utils/ExecuteHelper';
import ModulesHelper from '../utils/ModulesHelper';
import { installNodeService, installWebApp } from './install';
import Modules from '../config/Modules';

interface LocalCommandOptions {
  type: string,
  module: string,
  port?: string,
  env: string,
  server?: boolean,
  skipInstall?: boolean,
}

const local = (options: LocalCommandOptions) => {
  const { type, module, env } = options;
  if (!type || !module || !env) {
    Printer.error('未指定 type、module 和/或 env', { type, module, env });
  }
  switch (type) {
    case Enums.ModuleType.App: runWebApp(options); break;
    case Enums.ModuleType.Service: runNodeService(options); break;
    default: break;
  }
};

const runWebApp = (options: LocalCommandOptions) => {
  const { module, env, skipInstall } = options;
  if (!skipInstall) {
    installWebApp(options);
  }
  if (Modules.isExternalApp(module)) {
    runExternalWebApp(options);
    return;
  }
  const { commandRunDirectory, viteConfigPath } = ModulesHelper.buildWebAppExecuteParams(module);
  ExecuteHelper.run(
    'yarn run-dev',
    {
      cwd: commandRunDirectory,
      env: {
        NODE_ENV: 'development',
        VITE_API_ENV: env,
      },
    },
    { config: viteConfigPath },
  );
};

const runExternalWebApp = (options: LocalCommandOptions) => {
  const { module, env } = options;
  const { commandRunDirectory } = ModulesHelper.buildExternalWebAppExecuteParams(module);
  ExecuteHelper.run(
    ModulesHelper.buildExternalWebAppYarnCommand(module, 'run-dev'),
    {
      cwd: commandRunDirectory,
      env: {
        NODE_ENV: 'development',
        API_ENV: env,
      },
    },
  );
};

const runNodeService = (options: LocalCommandOptions) => {
  const { module, env, port, server: willRunInServer, skipInstall } = options;
  if (!skipInstall) {
    installNodeService(options);
  }
  const { commandRunDirectory } = ModulesHelper.buildNodeServiceExecuteParams(module);
  ExecuteHelper.run(
    willRunInServer ? 'yarn start' : 'yarn dev',
    {
      cwd: commandRunDirectory,
      env: {
        NODE_ENV: willRunInServer ? 'production' : 'development',
        PORT: port,
        ENV: env,
      },
    },
  );
};

const moduleTypes = Object.values<string>(Enums.ModuleType);
const moduleTypesString = moduleTypes.map((type) => colors.green(type)).join('、');

export default program
  .command('local')
  .description('启动 app web server 或 node service')
  .option('-t, --type [type]', `类型，可取值：${moduleTypesString}`)
  .option(
    '-m, --module [name]',
    `app 或 service 的名字，如 ${colors.green('userManagement')}、${colors.green('proxy')}`,
  )
  .option('-p, --port [port]', '指定 service 运行的端口（对 app 无效）')
  .option('-e, --env [env]', '指定 app 或 service 连接的环境')
  .option('-s, --server', '在服务器中启动服务，启动时会将 NODE_ENV 设置为 production')
  .option('-S, --skip-install', '跳过初始化阶段，用于在无法访问软件源时使用')
  .action(local);
